Esperaría que str.replace(/^/gm, "\t") se inserte delante de cada línea a \t . Este parece ser el caso, pero solo si usa terminaciones LF, cuando usa terminaciones CRLF, sucede algo extraño, lo inserta también entre \r\n .
Considere este código de ejemplo:
var str1 = "First line\nnext Line"; var str2 = "First line\r\nnext Line"; function escape(str) { return str.replace(/[\r\n\t]/g, match => { return { '\r': '\\r', '\n': '\\n', '\t': '\\t', }[match] }) } console.log("First string:") console.log(escape(str1)) console.log("Second string:") console.log(escape(str2)) function operation(str) { return str.replace(/^/gm, "\t"); } console.log("First string:") str1 = operation(str1) console.log(escape(str1)) console.log("Second string:") str2 = operation(str2) console.log(escape(str2)) .as-console-wrapper { max-height: 100% !important; } Después de la transformación, la primera cadena es como se esperaba \tFirst line\n\tnext Line , sin embargo, la segunda da como resultado \tFirst line\r\t\n\tnext Line , lo que crea un comportamiento inesperado en una extensión de VScode que estaba usando. VSCode interpretaría cada \n y \r por separado y los reemplazaría con \n\r , lo que daría como resultado un formato no deseado. A la consola, no parece importarle, y lo mostró como se esperaba, de ahí la función de escape, para mostrar esos desagradables retornos de carro y saltos de línea.
¿Es este comportamiento esperado o un error en la biblioteca estándar de JavaScript?
Esto es exactamente de acuerdo con la especificación ECMAScript, 22.2.2.4 Semántica de tiempo de ejecución: CompileAssertion :
Assertion :: ^ 1. Return a new Matcher with parameters (x, c) that captures nothing and performs the following steps when called: a. Assert: x is a State. b. Assert: c is a Continuation. c. Let e be x's endIndex. d. If e = 0, or if Multiline is true and the character Input[e - 1] is one of LineTerminator, then i. Return c(x). e. Return failure. En otra parte, en la Sección 12.3, LineTerminator se define como uno de <LF> <CR> <LS> <PS> , por lo que \r y \n se ven como terminadores separados.
Probablemente, la solución más fácil es no usar el indicador m y hacer coincidir todos los tipos de finales de línea usted mismo (incluido \r , que se usó en Mac en el pasado):
>>> "foo\rbar\r\nbaz\nqux".replace(/(^|\r\n|\r|\n)/g, "$1\t") "\tfoo\r\tbar\r\n\tbaz\n\tqux" Tenga en cuenta que \r\n debe ir antes de \r para que coincida como una unidad.